#include "Terrain.h"
#include <Windows.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <SOIL.h>
#include <iostream>
using namespace std;

Terrain::Terrain(const char* hmapFile, const char* textureFile)
{
	int channels;
	unsigned char* imageData = SOIL_load_image(hmapFile, &m_X, &m_Z, &channels, SOIL_LOAD_L);

	GLuint texId = SOIL_load_OGL_texture
		(
		textureFile,
		SOIL_LOAD_AUTO,
		SOIL_CREATE_NEW_ID,
		SOIL_FLAG_MIPMAPS | /*SOIL_FLAG_INVERT_Y |*/ SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
		);

	m_NumVertices = m_X * m_Z;
	m_Vertices = new Point[m_NumVertices];
	for (int z = 0; z < m_Z; z++) {
		for (int x=0; x < m_X; x++) {
			m_Vertices[z * m_X + x].x = (x - m_X/2)* 1;
			m_Vertices[z * m_X + x].y = (float)(imageData[z * m_X + x]/256.f) * 20.f;
			m_Vertices[z * m_X + x].z = (z - m_Z/2)* 1;
		}
	}

	m_TexCoords = new TexCoord[m_NumVertices];
	for (int z = 0; z < m_Z; z++) {
		for (int x=0; x < m_X; x++) {
			m_TexCoords[z * m_X + x].s = x/(m_X*1.f);
			m_TexCoords[z * m_X + x].t = z/(m_Z*1.f);
		}
	}

	m_NumTriangles = 2*(m_X - 1)*(m_Z - 1);
	m_Triangles = new Triangle[m_NumTriangles];
	int pos = 0;

	for (int z = 0; z < m_Z-1; z++) {
		for (int x=0; x < m_X-1; x++) {
			m_Triangles[pos].p1 = z * m_X + x;
			m_Triangles[pos].p2 = (z+1) * m_X + x;
			m_Triangles[pos].p3 = z * m_X + (x+1);
			pos++;
			m_Triangles[pos].p1 = (z+1) * m_X + x;
			m_Triangles[pos].p2 = z * m_X + (x+1);
			m_Triangles[pos].p3 = (z+1) * m_X + (x+1);
			pos++;
		}
	}

	dlist = glGenLists(1);
	glNewList(dlist, GL_COMPILE);
	glBindTexture(GL_TEXTURE_2D, texId);

	for (int i=0; i < m_NumTriangles; ++i) {
		Triangle triangle = m_Triangles[i];
		glBegin(GL_TRIANGLES);
		glTexCoord2f(m_TexCoords[triangle.p1].s, m_TexCoords[triangle.p1].t);
		glVertex3f(m_Vertices[triangle.p1].x, m_Vertices[triangle.p1].y, m_Vertices[triangle.p1].z);
		glTexCoord2f(m_TexCoords[triangle.p2].s, m_TexCoords[triangle.p2].t);
		glVertex3f(m_Vertices[triangle.p2].x, m_Vertices[triangle.p2].y, m_Vertices[triangle.p2].z);
		glTexCoord2f(m_TexCoords[triangle.p3].s, m_TexCoords[triangle.p3].t);
		glVertex3f(m_Vertices[triangle.p3].x, m_Vertices[triangle.p3].y, m_Vertices[triangle.p3].z);
		glEnd();
	}
	
	glEndList();

	if (pos != m_NumTriangles) std::cout << "Error : Triangle count wrong\n";
	else std::cout << "Info : Terrain generation completed\n";
}

Terrain::~Terrain(void)
{
}

float Terrain::getHeight(int x, int z)
{
	return m_Vertices[z * m_X + x].y;
}

void Terrain::draw() 
{
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_COLOR_MATERIAL);
	glPushMatrix();
	glCallList(dlist);
	glPopMatrix();
	glEnable(GL_COLOR_MATERIAL);
	glDisable(GL_TEXTURE_2D);
}

//Triangle* Terrain::getTriangles()
//{
//	return m_Triangles;
//}

int	Terrain::getTriangleCount()
{
	return m_NumTriangles;
}

void Terrain::buildPhysicsMesh(neSimulator* gSim)
{
	std::cout << "Terrain mesh building stated\n";
	neTriangleMesh triMesh;

	neV3* vertices = new neV3[m_NumVertices];
	for (int i=0; i < m_NumVertices; ++i) {
		vertices[i].Set(m_Vertices[i].x, m_Vertices[i].y, m_Vertices[i].z);
	}

	triMesh.vertices = vertices;
	triMesh.vertexCount = m_NumVertices;

	neTriangle* triangles = new neTriangle[m_NumTriangles];
	for (int i=0; i < m_NumTriangles; ++i) {
		triangles[i].indices[0] = m_Triangles[i].p1;
		triangles[i].indices[1] = m_Triangles[i].p2;
		triangles[i].indices[2] = m_Triangles[i].p3;
	}

	triMesh.triangles = triangles;
	triMesh.triangleCount = m_NumTriangles;

	gSim->SetTerrainMesh(&triMesh);

	delete[] vertices;
	delete[] triangles;
	std::cout << "Terrain mesh building finished\n";
}